package com.vhall.component.service.rbac.impl;


import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.vhall.component.dao.rbac.RbacActionsMapper;
import com.vhall.component.dao.rbac.RbacRoleActionsMapper;
import com.vhall.component.entity.account.ActionsEntity;
import com.vhall.component.entity.account.RoleActionsEntity;
import com.vhall.component.entity.rbac.vo.ActionsRspVO;
import com.vhall.component.entity.rbac.vo.ActionsVO;
import com.vhall.component.framework.common.exception.BusinessException;
import com.vhall.component.framework.common.utils.StringUtils;
import com.vhall.component.plugin.common.constant.RedisKey;
import com.vhall.component.plugin.common.exception.BizErrorCode;
import com.vhall.component.service.rbac.RbacRoleActionService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author dalong
 * @date 2021-05-18 14:59
 */
@Service
public class RbacRoleActionServiceImpl implements RbacRoleActionService {

    @Autowired
    private RbacRoleActionsMapper roleActionsMapper;

    @Autowired
    private RbacActionsMapper actionsMapper;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Override
    public List<Integer> getActionIdListByRoleId(Integer roleId) {
        List<Integer> actionIdList = new ArrayList<>();
        LambdaQueryWrapper<RoleActionsEntity> where = Wrappers.lambdaQuery();
        where.eq(RoleActionsEntity::getRoleId, roleId)
                .isNull(RoleActionsEntity::getDeletedAt);
        List<RoleActionsEntity> list = roleActionsMapper.selectList(where);
        if (list.size() <= 0) {
            return actionIdList;
        }
        actionIdList = list.stream().map(RoleActionsEntity::getActionId).collect(Collectors.toList());
        return actionIdList;
    }

    @Override
    public List<ActionsRspVO> getActionsListByActionIdList(List<Integer> actionIdList, Integer roleId) {
        List<ActionsRspVO> actionsRspVOList = new LinkedList<>();
        if (actionIdList.size() <= 0) {
            return actionsRspVOList;
        }
        LambdaQueryWrapper<ActionsEntity> where = Wrappers.lambdaQuery();
        where.in(ActionsEntity::getActionId, actionIdList)
                .isNull(ActionsEntity::getDeletedAt);
        List<ActionsEntity> list = actionsMapper.selectList(where);
        if (list.size() <= 0) {
            throw new BusinessException(BizErrorCode.EMPTY_ROLE);
        }

        for (ActionsEntity actionsEntity : list) {
            ActionsRspVO actionsRspVO = new ActionsRspVO();
            BeanUtils.copyProperties(actionsEntity, actionsRspVO);
            actionsRspVO.setRoleId(roleId);
            actionsRspVOList.add(actionsRspVO);
        }
        return actionsRspVOList;
    }

    @Override
    public boolean initRoleActionList(Integer roleId) {
        // 设置初始角色操作权限
        Integer[] initRoleActionList = {10, 11, 12, 32, 45, 46, 48, 57};
        for (Integer actionId : initRoleActionList) {
            Integer actionsCount = actionsMapper.selectCount(Wrappers.<ActionsEntity>lambdaQuery().eq(ActionsEntity::getActionId, actionId));
            if (actionsCount > 0) {
                LambdaQueryWrapper<RoleActionsEntity> where = Wrappers.lambdaQuery();
                where.eq(RoleActionsEntity::getRoleId, roleId)
                        .eq(RoleActionsEntity::getActionId, actionId)
                        .isNull(RoleActionsEntity::getDeletedAt)
                        .last("LIMIT 1");
                RoleActionsEntity roleActionsEntity = roleActionsMapper.selectOne(where);
                if (roleActionsEntity == null) {
                    roleActionsEntity = new RoleActionsEntity();
                    roleActionsEntity.setRoleId(roleId);
                    roleActionsEntity.setActionId(actionId);
                    roleActionsEntity.setCreatedAt(LocalDateTime.now());
                    roleActionsEntity.setUpdatedAt(LocalDateTime.now());
                    roleActionsMapper.insert(roleActionsEntity);
                }
            }
        }
        List<ActionsEntity> actionsEntities = actionsMapper.selectList(Wrappers.<ActionsEntity>lambdaQuery().in(ActionsEntity::getActionId, Arrays.asList(initRoleActionList)));
        Set<String> perm = new HashSet<>();
        for (ActionsEntity action : actionsEntities) {
            if (StringUtils.isNotEmpty(action.getActionTag())) {
                perm.add(action.getActionTag());
            }
        }
        String key = RedisKey.ROLE_PERMISSION + roleId;
        redisTemplate.opsForValue().set(key, JSON.toJSONString(perm));
        return true;
    }

    @Override
    public List<ActionsVO> listActionByRoleId(Integer roleId) {
        List<ActionsEntity> actionsEntities = new ArrayList<>();
        List<Integer> actionIds = getActionIdListByRoleId(roleId);
        if (actionIds.size() > 0) {
            LambdaQueryWrapper<ActionsEntity> where = Wrappers.lambdaQuery();
            where.in(ActionsEntity::getActionId, actionIds).isNull(ActionsEntity::getDeletedAt);
            actionsEntities = actionsMapper.selectList(where);
        }
        List<ActionsVO> actionsVos = new ArrayList<>();
        for (ActionsEntity actionsEntity : actionsEntities) {
            ActionsVO actionsVO = new ActionsVO();
            BeanUtils.copyProperties(actionsEntity, actionsVO);
            actionsVos.add(actionsVO);
        }
        return actionsVos;
    }
}
